Passed
Push — main ( 997d4c...4c4485 )
by Andrii
02:35
created

ctx.ts ➔ classNamer   A

Complexity

Conditions 4

Size

Total Lines 39
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 29
dl 0
loc 39
rs 9.184
c 0
b 0
f 0
cc 4
1
import type { ToggleMap, ClassNamer, ClassNamed, ClassNamesMap, EmptyObject } from "./defs"
2
import {dehash, joinWithLead, truthyKeys, wrapper} from "./core"
3
import { emptize } from "./utils"
4
5
emptize(classNamer)
6
7
//TODO no `className` - no first `true`
8
interface tClassNaming<
9
  ClassKeys extends string,
10
  withClassNames extends boolean | undefined
11
> {
12
  /**
13
   * @example classes(true) === props.className
14
   * @example classes({class1: true, class2: false}) === "class1"
15
   * @example classes(true, {class1: true, class2: false})
16
  */
17
 // Using overloads will make error not in certain argument but on all call - 'No overload found'
18
  (
19
    propagate_or_map_or_expression?: true | ToggleMap<ClassKeys>,
20
    map_or_expression?: [Extract<typeof propagate_or_map_or_expression, true>] extends [never]
21
    ? never
22
    : ToggleMap<ClassKeys>
23
  ) : ClassNamed & (
24
    withClassNames extends true
25
    ? {classnames: ClassNamesMap<ClassKeys>}
26
    : EmptyObject
27
  ) 
28
}
29
30
export default classNamingCtx
31
32
/**
33
 * @example const classes = classNamingCtx(this.props)
34
 * @example const classes = classNamingCtx({className, classnames})
35
 * @example const classes = classNamingCtx({classnames})
36
 */
37
function classNamingCtx<
38
  ClassKeys extends string,
39
  withClassNames extends boolean|undefined
40
>(
41
  {classnames, className}: ClassNamer<ClassKeys>,
42
  options?: ClassNamerOptions<withClassNames>
43
) {
44
  return classNamer.bind({classnames, className, options}) as tClassNaming<ClassKeys, withClassNames>
45
}
46
47
type ClassNamerOptions<
48
  withClassNames extends undefined|boolean
49
> = Partial<{
50
  withClassNames: withClassNames
51
  // withSelf: boolean
52
}>
53
54
function classNamer<
55
  ClassKeys extends string,
56
  withClassNames extends boolean|undefined
57
>(
58
  this: Partial<ClassNamer<ClassKeys> & {options: ClassNamerOptions<withClassNames>}>,
59
  arg0?: true | ToggleMap<ClassKeys>,
60
  arg1?: typeof arg0 extends true ? ToggleMap<ClassKeys> : never,
61
): ClassNamed & Partial<Pick<typeof this, "classnames">> {
62
  const {
63
    className: propagated,
64
    classnames,
65
    options
66
  } = this
67
  , {
68
    withClassNames,
69
    // withSelf
70
  } = options ?? {}
71
  , withPropagation = arg0 === true
72
  , allowed: ClassKeys[] = truthyKeys(arg0 === true ? arg1 : arg0)
73
  //@ts-expect-error
74
  .filter<ClassKeys>(
75
    Boolean
76
  )
77
  
78
  emptize(classnames)
79
80
  classnames && dehash(classnames, allowed)
81
  
82
  const className = joinWithLead(withPropagation && propagated, allowed)
83
  , host = classNamer.bind({classnames, className, options})
84
85
  withClassNames && (
86
    //@ts-expect-error
87
    host["classnames"] = classnames
88
  )
89
  return wrapper(
90
    host,
91
    className,
92
  )
93
}